package io.aicn.lowcode.generator.independent;

import io.aicn.lowcode.generator.independent.constant.CodeTemplates;
import io.aicn.lowcode.generator.independent.engine.TemplateEngine;
import io.aicn.lowcode.generator.independent.model.IndependentControllerConfig;
import io.aicn.lowcode.generator.independent.model.IndependentEntityConfig;
import io.aicn.lowcode.generator.independent.model.IndependentGenerationRequest;
import io.aicn.lowcode.generator.independent.model.IndependentGenerationResult;
import io.aicn.lowcode.generator.independent.model.IndependentMapperConfig;
import io.aicn.lowcode.generator.independent.model.IndependentServiceConfig;
import io.aicn.lowcode.generator.independent.util.FileWriteUtil;
import io.aicn.lowcode.generator.model.ColumnInfo;
import io.aicn.lowcode.generator.model.TableInfo;
import io.aicn.lowcode.service.DatabaseSchemaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class IndependentCodeGenerator {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private DatabaseSchemaService databaseSchemaService;

    @Autowired
    private TemplateEngine templateEngine;

    @Autowired
    private FileWriteUtil fileWriteUtil;

    public IndependentGenerationResult generateCode(IndependentGenerationRequest request) {
        try {
            // 1. 获取表信息
            io.aicn.lowcode.generator.model.TableInfo tableInfo = databaseSchemaService.getTableInfo(request.getTableName());

            // 2. 构建上下文
            Map<String, Object> context = buildContext(request, tableInfo);

            // 3. 生成文件
            List<String> generatedFiles = new ArrayList<>();

            // 生成Entity
            if (request.getEntityConfig() != null) {
                String entityFile = generateEntity(context, request);
                generatedFiles.add(entityFile);
            }

            // 生成Mapper
            if (request.getMapperConfig() != null) {
                String mapperInterfaceFile = generateMapperInterface(context, request);
                generatedFiles.add(mapperInterfaceFile);

                if (request.getMapperConfig().isXmlEnabled()) {
                    String mapperXmlFile = generateMapperXml(context, request);
                    generatedFiles.add(mapperXmlFile);
                }
            }

            // 生成Service
            if (request.getServiceConfig() != null) {
                if (request.getServiceConfig().isInterfaceEnabled()) {
                    String serviceInterfaceFile = generateServiceInterface(context, request);
                    generatedFiles.add(serviceInterfaceFile);
                }

                String serviceImplFile = generateServiceImpl(context, request);
                generatedFiles.add(serviceImplFile);

                // 生成单元测试
                if (request.isGenerateTests()) {
                    String serviceTestFile = generateServiceTest(context, request);
                    generatedFiles.add(serviceTestFile);
                }
            }

            // 生成Controller
            if (request.getControllerConfig() != null) {
                String controllerFile = generateController(context, request);
                generatedFiles.add(controllerFile);
            }

            return new IndependentGenerationResult(true, "代码生成成功", generatedFiles);

        } catch (Exception e) {
            return new IndependentGenerationResult(false, "代码生成失败: " + e.getMessage(), null);
        }
    }

    private Map<String, Object> buildContext(IndependentGenerationRequest request, TableInfo tableInfo) {
        Map<String, Object> context = new HashMap<>();

        // 基础配置
        context.put("basePackage", request.getBasePackage());
        context.put("author", request.getAuthor());
        context.put("date", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        // Entity配置
        if (request.getEntityConfig() != null) {
            Map<String, Object> entityConfig = new HashMap<>();
            entityConfig.put("packageName", request.getBasePackage() + ".entity");
            entityConfig.put("className", request.getEntityConfig().getClassName());
            entityConfig.put("tableName", request.getEntityConfig().getTableName());
            entityConfig.put("superClass", null);
            entityConfig.put("lombok", request.getEntityConfig().isLombok());
            entityConfig.put("swagger", request.getEntityConfig().isSwagger());
            entityConfig.put("serialVersionUID", false);
            entityConfig.put("tableComment", request.getEntityConfig().getTableComment());
            context.put("entity", entityConfig);
        }

        // Mapper配置
        if (request.getMapperConfig() != null) {
            Map<String, Object> mapperConfig = new HashMap<>();
            mapperConfig.put("packageName", request.getBasePackage() + ".mapper");
            mapperConfig.put("className", request.getMapperConfig().getClassName());
            mapperConfig.put("entityClassName", request.getMapperConfig().getEntityClassName());
            mapperConfig.put("tableName", request.getMapperConfig().getTableName());
            mapperConfig.put("xmlEnabled", request.getMapperConfig().isXmlEnabled());
            context.put("mapper", mapperConfig);
        }

        // Service配置
        if (request.getServiceConfig() != null) {
            Map<String, Object> serviceConfig = new HashMap<>();
            serviceConfig.put("packageName", request.getBasePackage() + ".service");
            serviceConfig.put("className", request.getServiceConfig().getClassName());
            serviceConfig.put("interfaceName", request.getServiceConfig().getInterfaceName());
            serviceConfig.put("entityClassName", request.getServiceConfig().getEntityClassName());
            serviceConfig.put("mapperClassName", request.getServiceConfig().getMapperClassName());
            serviceConfig.put("interfaceEnabled", request.getServiceConfig().isInterfaceEnabled());
            context.put("service", serviceConfig);
        }

        // Controller配置
        if (request.getControllerConfig() != null) {
            Map<String, Object> controllerConfig = new HashMap<>();
            controllerConfig.put("packageName", request.getBasePackage() + ".controller");
            controllerConfig.put("className", request.getControllerConfig().getClassName());
            controllerConfig.put("entityClassName", request.getControllerConfig().getEntityClassName());
            controllerConfig.put("serviceClassName", request.getControllerConfig().getServiceClassName());
            controllerConfig.put("restStyle", request.getControllerConfig().isRestStyle());
            controllerConfig.put("enableSwagger", request.getControllerConfig().isEnableSwagger());
            controllerConfig.put("apiPath", request.getControllerConfig().getApiPath());
            context.put("controller", controllerConfig);
        }

        // 字段信息
        List<Map<String, Object>> fields = new ArrayList<>();
        Map<String, Object> primaryKey = null;

        for (io.aicn.lowcode.generator.model.ColumnInfo column : tableInfo.getColumns()) {
            Map<String, Object> field = new HashMap<>();
            field.put("name", column.getName());
            field.put("javaType", column.getJavaType());
            field.put("javaProperty", column.getJavaProperty());
            field.put("comment", column.getComment());
            field.put("primaryKey", column.getPrimaryKey() != null && column.getPrimaryKey());
            field.put("autoIncrement", column.getAutoIncrement() != null && column.getAutoIncrement());
            fields.add(field);

            if (column.getPrimaryKey() != null && column.getPrimaryKey()) {
                primaryKey = field;
                primaryKey.put("testValue", getTestValue(column.getJavaType()));
            }
        }

        context.put("fields", fields);
        context.put("primaryKey", primaryKey);

        return context;
    }

    private String getTestValue(String javaType) {
        switch (javaType) {
            case "Long":
                return "1L";
            case "Integer":
                return "1";
            case "String":
                return "\"test\"";
            case "Boolean":
                return "true";
            default:
                return "null";
        }
    }

    private String generateEntity(Map<String, Object> context, IndependentGenerationRequest request) throws IOException {
        String content = templateEngine.processTemplate(CodeTemplates.ENTITY_TEMPLATE, context);
        
        String packageName = (String) ((Map<String, Object>) context.get("entity")).get("packageName");
        String className = (String) ((Map<String, Object>) context.get("entity")).get("className");
        
        String filePath = String.format("%s/java/%s/%s.java", 
                request.getOutputDir(),
                packageName.replace('.', '/'),
                className);
        
        fileWriteUtil.writeFile(filePath, content);
        return filePath;
    }

    private String generateMapperInterface(Map<String, Object> context, IndependentGenerationRequest request) throws IOException {
        String content = templateEngine.processTemplate(CodeTemplates.MAPPER_INTERFACE_TEMPLATE, context);
        
        String packageName = (String) ((Map<String, Object>) context.get("mapper")).get("packageName");
        String className = (String) ((Map<String, Object>) context.get("mapper")).get("className");
        
        String filePath = String.format("%s/java/%s/%s.java", 
                request.getOutputDir(),
                packageName.replace('.', '/'),
                className);
        
        fileWriteUtil.writeFile(filePath, content);
        return filePath;
    }

    private String generateMapperXml(Map<String, Object> context, IndependentGenerationRequest request) throws IOException {
        String content = templateEngine.processTemplate(CodeTemplates.MAPPER_XML_TEMPLATE, context);
        
        String className = (String) ((Map<String, Object>) context.get("mapper")).get("className");
        
        String filePath = String.format("%s/resources/mapper/%s.xml", 
                request.getOutputDir(),
                className);
        
        fileWriteUtil.writeFile(filePath, content);
        return filePath;
    }

    private String generateServiceInterface(Map<String, Object> context, IndependentGenerationRequest request) throws IOException {
        String content = templateEngine.processTemplate(CodeTemplates.SERVICE_INTERFACE_TEMPLATE, context);
        
        String packageName = (String) ((Map<String, Object>) context.get("service")).get("packageName");
        String interfaceName = (String) ((Map<String, Object>) context.get("service")).get("interfaceName");
        
        String filePath = String.format("%s/java/%s/%s.java", 
                request.getOutputDir(),
                packageName.replace('.', '/'),
                interfaceName);
        
        fileWriteUtil.writeFile(filePath, content);
        return filePath;
    }

    private String generateServiceImpl(Map<String, Object> context, IndependentGenerationRequest request) throws IOException {
        String content = templateEngine.processTemplate(CodeTemplates.SERVICE_IMPL_TEMPLATE, context);
        
        String packageName = (String) ((Map<String, Object>) context.get("service")).get("packageName");
        String className = (String) ((Map<String, Object>) context.get("service")).get("className");
        
        String filePath = String.format("%s/java/%s/impl/%s.java", 
                request.getOutputDir(),
                packageName.replace('.', '/'),
                className);
        
        fileWriteUtil.writeFile(filePath, content);
        return filePath;
    }

    private String generateController(Map<String, Object> context, IndependentGenerationRequest request) throws IOException {
        String content = templateEngine.processTemplate(CodeTemplates.CONTROLLER_TEMPLATE, context);
        
        String packageName = (String) ((Map<String, Object>) context.get("controller")).get("packageName");
        String className = (String) ((Map<String, Object>) context.get("controller")).get("className");
        
        String filePath = String.format("%s/java/%s/%s.java", 
                request.getOutputDir(),
                packageName.replace('.', '/'),
                className);
        
        fileWriteUtil.writeFile(filePath, content);
        return filePath;
    }

    private String generateServiceTest(Map<String, Object> context, IndependentGenerationRequest request) throws IOException {
        String content = templateEngine.processTemplate(CodeTemplates.SERVICE_TEST_TEMPLATE, context);
        
        String packageName = (String) ((Map<String, Object>) context.get("service")).get("packageName");
        String interfaceName = (String) ((Map<String, Object>) context.get("service")).get("interfaceName");
        
        String filePath = String.format("%s/test/java/%s/%sTest.java", 
                request.getOutputDir(),
                packageName.replace('.', '/'),
                interfaceName);
        
        fileWriteUtil.writeFile(filePath, content);
        return filePath;
    }
}